#!/bin/sh

# Author: Zhang Huangbin (michaelbibby <at> gmail.com)
# $Date: 2008-03-03 22:38:45 +0800 (Mon, 03 Mar 2008) $
# $Revision: 126 $

ROOTDIR="$(pwd)"
CONF_DIR="${ROOTDIR}/conf"
TOOLS_DIR="${ROOTDIR}/tools"
PKG_DIR="${ROOTDIR}/pkgs/$(uname -i)/rpms"
MISC_DIR="${ROOTDIR}/pkgs/$(uname -i)/misc"
SAMPLE_DIR="${ROOTDIR}/samples"

. ${CONF_DIR}/global
. ${CONF_DIR}/functions

check_env

. ${CONF_DIR}/httpd
. ${CONF_DIR}/openldap
. ${CONF_DIR}/phpldapadmin
. ${CONF_DIR}/mysql
. ${CONF_DIR}/cyrus_sasl
. ${CONF_DIR}/postfix
. ${CONF_DIR}/maildrop
. ${CONF_DIR}/courier
. ${CONF_DIR}/amavisd
. ${CONF_DIR}/spamassassin
. ${CONF_DIR}/squirrelmail
. ${CONF_DIR}/roundcube
. ${CONF_DIR}/postfixadmin

# -------------------------------------------------------
# ---------------- User/Group: vmail --------------------
# -------------------------------------------------------
adduser_vmail()
{
    ECHO_INFO "Add user/group: vmail."
    groupadd -g ${VMAIL_USER_GID} ${VMAIL_GROUP_NAME}
    useradd -m -d ${VMAIL_USER_HOME_DIR} -s /sbin/nologin -u ${VMAIL_USER_UID} -g ${VMAIL_USER_GID} ${VMAIL_USER_NAME}
    rm -f ${VMAIL_USER_HOME_DIR}/.* 2>/dev/null
}

# -------------------------------------------------------
# ---------------- Apache & PHP -------------------------
# -------------------------------------------------------
apache_php_install()
{
    # Installation.
    install_pkg httpd php php-imap php-gd php-mbstring
    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        install_pkg php-ldap 
    else
        install_pkg php-mysql
    fi

    # Enable services.
    chkconfig --level 35 httpd on
}

apache_php_config()
{
    ECHO_INFO "Increase PHP 'memory_limit' to 64M."
    backup_file ${PHP_INI}
    perl -pi -e 's/^(memory_limit = )/${1}64M ;/' ${PHP_INI}
}

# -------------------------------------------------------
# ------------------- OpenLDAP --------------------------
# -------------------------------------------------------
openldap_install()
{
    # Installation.
    install_pkg openldap openldap-clients openldap-servers

    # Copy qmail.schema.
    cp ${SAMPLE_DIR}/qmail.schema ${OPENLDAP_SCHEMA_DIR}

    # Enable services.
    chkconfig --level 35 ldap on
}

openldap_config()
{
    backup_file ${OPENLDAP_SLAPD_CONF} ${OPENLDAP_LDAP_CONF}

    ECHO_INFO "Generate new configuration file: ${OPENLDAP_SLAPD_CONF}."
    cat > ${OPENLDAP_SLAPD_CONF} <<EOF
${CONF_MSG}
include     ${OPENLDAP_SCHEMA_DIR}/core.schema
include     ${OPENLDAP_SCHEMA_DIR}/corba.schema
include     ${OPENLDAP_SCHEMA_DIR}/cosine.schema
include     ${OPENLDAP_SCHEMA_DIR}/inetorgperson.schema
include     ${OPENLDAP_SCHEMA_DIR}/nis.schema

include     ${OPENLDAP_SCHEMA_DIR}/qmail.schema

pidfile     /var/run/openldap/slapd.pid
argsfile    /var/run/openldap/slapd.args

#
# Disallow bind as anonymous.
#
disallow    bind_anon

#
# Specify LDAP protocol version.
#require     LDAPv3
allow       bind_v2

# For debug
#loglevel    -1
#loglevel   256
loglevel    0

#
# Access Control List. Used for LDAP bind.
#
# NOTE: Every domain have a administrator.
#   For domain: '${FIRST_DOMAIN}'
#   Administrator:
#       mail=${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN}, o=${FIRST_DOMAIN}, ${LDAP_BASEDN}
#

#
# Set permission for LDAP attrs.
#
access to attrs="userPassword,mailForwardingAddress"
    by anonymous    auth
    by self         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${FIRST_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"   write
    by users        none
access to attrs="cn,sn"
    by anonymous    auth
    by self         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${FIRST_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"   write
    by users        read

access to attrs="destinationIndicator,mail,mailQuota,homeDirectory,mailMessageStore,mailForwardingAddress,accountStatus,objectclass"
    by anonymous    auth
    by self         read
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${FIRST_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"    write
    by users        read

#
# Set ACL for vmail/vmailadmin.
#
access to dn="${LDAP_BINDDN}"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by users                        none
access to dn="${LDAP_ADMIN_DN}"
    by anonymous                    auth
    by self                         write
    by users                        none

#
# Allow users to access their own domain subtree.
#
access to dn.regex="o=([^,]+),${LDAP_BASEDN}\$"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=admin@\$1,o=\$1,${LDAP_BASEDN}\$" write
    by dn.regex="mail=[^,]+,o=\$1,${LDAP_BASEDN}\$" read
    by users                        none
#
# Enable vmail/vmailadmin. 
#
access to dn.subtree="${LDAP_BASEDN}"
    by anonymous                    auth
    by self                         write
    by dn.exact="${LDAP_BINDDN}"   read
    by dn.exact="${LDAP_ADMIN_DN}"  write
    by dn.regex="mail=${FIRST_DOMAIN_ADMIN_NAME}@([^,]+),o=\$1,${LDAP_BASEDN}"    write
    by users                        read

#
# Set permission for "cn=*,${LDAP_SUFFIX}".
#
access to dn.regex="cn=[^,]+,${LDAP_SUFFIX}"
    by anonymous                    auth
    by self                         write
    by users                        none
#
# Set default permission.
#
access to *
    by anonymous                    auth
    by self                         write
    by users                        read

#######################################################################
# BDB database definitions
#######################################################################

database    bdb
suffix      "${LDAP_SUFFIX}"
directory   ${LDAP_DATA_DIR}

rootdn      "${LDAP_ROOTDN}"
rootpw      ${LDAP_ROOTPW}

#
# Set directory permission.
#
mode        0700

#
# Default index.
#
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub

#
# Index for mail attrs.
#
index       destinationIndicator,o   eq
index       homeDirectory,mailMessageStore,mailForwardingAddress,accountStatus eq
cachesize   1000
EOF

    ECHO_INFO "Generating new LDAP client configuration file: ${OPENLDAP_LDAP_CONF}"
    cat > ${OPENLDAP_LDAP_CONF} <<EOF
BASE    ${LDAP_SUFFIX}
URI     ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}
EOF

    ECHO_INFO "Setting up syslog configration file for openldap: /etc/syslog.conf"
    echo -e "local4.*\t\t\t\t\t\t${OPENLDAP_LOGFILE}" >>/etc/syslog.conf

    ECHO_INFO "Create empty log file for OpenLDAP: ${OPENLDAP_LOGFILE}."
    touch ${OPENLDAP_LOGFILE}
    chown ldap:ldap ${OPENLDAP_LOGFILE}
    chmod 0600 ${OPENLDAP_LOGFILE}

    ECHO_INFO "Setting logrotate for openldap log file."
    cat > /etc/logrotate.d/openldap <<EOF
${CONF_MSG}
${OPENLDAP_LOGFILE} {
    compress
    weekly
    rotate 5
    create 0600 ldap ldap
    missingok
    postrotate
        /sbin/killall -HUP syslogd
    endscript
}
EOF

    ECHO_INFO "Restarting syslog."
    /etc/init.d/syslog restart
}

openldap_data_initialize()
{
    ECHO_INFO "Create instance directory for openldap tree: ${LDAP_DATA_DIR}."
    mkdir -p ${LDAP_DATA_DIR}
    chown -R ldap:ldap ${OPENLDAP_DATA_DIR}
    chmod -R 0700 ${OPENLDAP_DATA_DIR}

    ECHO_INFO "Generate DB_CONFIG for instance: ${LDAP_DATA_DIR}/DB_CONFIG."
    cp ${OPENLDAP_ROOTDIR}/DB_CONFIG.example ${LDAP_DATA_DIR}/DB_CONFIG

    ECHO_INFO "Starting OpenLDAP."
    /etc/init.d/ldap restart && sleep 5

    ECHO_INFO "Initialization LDAP tree."
    cat > ${LDAP_INIT_LDIF} <<EOF
dn: ${LDAP_SUFFIX}
objectclass: dcObject
objectclass: organization
dc: ${LDAP_SUFFIX_MAJOR}
o: ${LDAP_SUFFIX_MAJOR}

dn: o=${LDAP_BASEDN_NAME},${LDAP_SUFFIX}
objectClass: Organization
o: ${LDAP_BASEDN_NAME}

dn: ${LDAP_BINDDN}
objectClass: person
objectClass: top
cn: ${VMAIL_USER_NAME}
sn: ${VMAIL_USER_NAME}
userPassword: ${LDAP_BINDPW}

dn: ${LDAP_ADMIN_DN}
objectClass: person
objectClass: top
cn: ${VMAIL_ADMIN_USER_NAME}
sn: ${VMAIL_ADMIN_USER_NAME}
userPassword: ${LDAP_ADMIN_PW}

dn: o=${FIRST_DOMAIN},${LDAP_BASEDN}
objectClass: Organization
o: ${FIRST_DOMAIN}
destinationIndicator: maildrop

dn: mail=${FIRST_USER}@${FIRST_DOMAIN},o=${FIRST_DOMAIN},${LDAP_BASEDN}
objectClass: inetOrgPerson
objectClass: qmailUser
objectClass: top
cn: ${FIRST_USER}
sn: ${FIRST_USER}
uid: ${FIRST_USER}
mail: ${FIRST_USER}@${FIRST_DOMAIN}
accountStatus: active
homeDirectory: ${VMAIL_USER_HOME_DIR}
mailMessageStore: ${FIRST_DOMAIN}/${FIRST_USER}/${MAILDIR_NAME}
mailQuota: 1024000S
userPassword: ${FIRST_USER_PASSWD}

dn: mail=${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN},o=${FIRST_DOMAIN},${LDAP_BASEDN}
objectClass: inetOrgPerson
objectClass: qmailUser
objectClass: top
cn: ${FIRST_DOMAIN_ADMIN_NAME}
sn: ${FIRST_DOMAIN_ADMIN_NAME}
uid: ${FIRST_DOMAIN_ADMIN_NAME}
mail: ${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN}
accountStatus: active
homeDirectory: ${VMAIL_USER_HOME_DIR}
mailMessageStore: ${FIRST_DOMAIN}/${FIRST_DOMAIN_ADMIN_NAME}/${MAILDIR_NAME}
mailQuota: 0S
userPassword: ${FIRST_DOMAIN_ADMIN_PASSWD}
EOF

    ldapadd -x -D "${LDAP_ROOTDN}" -w "${LDAP_ROOTPW}" -f ${LDAP_INIT_LDIF}
}

# -------------------------------------------------------
# ------------------- phpLDAPadmin ----------------------
# -------------------------------------------------------
pla_install()
{
    cd ${MISC_DIR}

    ECHO_INFO "Extract phpLDAPadmin: ${PLA_TARBALL}..."
    extract_pkg ${PLA_TARBALL} ${HTTPD_SERVERROOT}

    ECHO_INFO "Create directory alias for phpLDAPadmin."
    cat > ${HTTPD_CONF_DIR}/phpldapadmin.conf <<EOF
${CONF_MSG}
Alias /phpldapadmin "/var/www/phpldapadmin-${PLA_VERSION}/"
Alias /ldap "/var/www/phpldapadmin-${PLA_VERSION}/"
EOF
    ECHO_INFO "URL of phpLDAPadmin: http://${hostname}/phpldapadmin/"
    ECHO_INFO "URL of phpLDAPadmin: http://${hostname}/ldap/"

    ECHO_INFO "Copy example config file."
    cd ${HTTPD_SERVERROOT}/phpldapadmin-${PLA_VERSION}/config/
    cp config.php.example config.php

    ECHO_INFO "Add phpLDAPadmin templates for create virtual domains/users."
    cp -f ${TOOLS_DIR}/phpldapadmin/template/*xml \
        ${HTTPD_SERVERROOT}/phpldapadmin-${PLA_VERSION}/templates/creation/

    ECHO_INFO "You should click 'Purge Cache' link to enable these templates while you login into phpldapadmin."
}

# -------------------------------------------------------
# -------------------- MySQL ----------------------------
# -------------------------------------------------------
mysql_install()
{
    # Installation.
    install_pkg mysql mysql-server

    # Enable services.
    chkconfig --level 35 mysqld on
}

mysql_initialize()
{
    ECHO_INFO "Starting MySQL."
    /etc/init.d/mysqld restart

    ECHO_INFO "Setting root password."
    /usr/bin/mysqladmin -u root password "${MYSQL_ROOTPW}"

    ECHO_INFO "Initialize database for postfix virtual hosts."

    SITE_ADMIN_PASSWD="$(openssl passwd -1 ${SITE_ADMIN_PASSWD})"
    FIRST_DOMAIN_ADMIN_PASSWD="$(openssl passwd -1 ${FIRST_DOMAIN_ADMIN_PASSWD})"
    FIRST_USER_PASSWD="$(openssl passwd -1 ${FIRST_USER_PASSWD})"

    mysql -uroot -p${MYSQL_ROOTPW} <<EOF
/* Create database for virtual hosts.*/
USE mysql;
CREATE DATABASE IF NOT EXISTS ${VMAIL_DB};

/* Permissions. */
GRANT USAGE ON ${VMAIL_DB}.* TO ${MYSQL_BIND_USER}@localhost;
GRANT SELECT ON ${VMAIL_DB}.* TO ${MYSQL_BIND_USER}@localhost IDENTIFIED by "${MYSQL_BIND_PW}";

GRANT USAGE ON ${VMAIL_DB}.* TO ${MYSQL_ADMIN_USER}@localhost;
GRANT SELECT, INSERT, DELETE, UPDATE ON ${VMAIL_DB}.* TO ${MYSQL_ADMIN_USER}@localhost IDENTIFIED BY "${MYSQL_ADMIN_PW}";

/* Initialize the database. */
USE ${VMAIL_DB};
source ${SAMPLE_SQL};

/* Add site admin. */
INSERT INTO admin (username, password) VALUES("${SITE_ADMIN_NAME}","${SITE_ADMIN_PASSWD}");
INSERT INTO domain_admins (username,domain) VALUES ("${SITE_ADMIN_NAME}","ALL");

/* Add your first domain. */
INSERT INTO domain (domain,transport) VALUES ("${FIRST_DOMAIN}", "maildrop");

/* Add your first domain admin. */
INSERT INTO admin (username, password) VALUES ("${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN}","${FIRST_DOMAIN_ADMIN_PASSWD}");

INSERT INTO domain_admins (username,domain) VALUES ("${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN}","${FIRST_DOMAIN}");

INSERT INTO mailbox (username,password,maildir,quota) VALUES ("${FIRST_DOMAIN_ADMIN_NAME}@${FIRST_DOMAIN}","${FIRST_DOMAIN_ADMIN_PASSWD}","${FIRST_DOMAIN}/${FIRST_DOMAIN_ADMIN_NAME}/Maildir/",0);

/* Add your first user. */
INSERT INTO mailbox (username,password,maildir,quota) VALUES ("${FIRST_USER}@${FIRST_DOMAIN}","${FIRST_USER_PASSWD}","${FIRST_DOMAIN}/${FIRST_USER}/Maildir/",1024000);

flush privileges;
EOF
}

# -------------------------------------------------------
# ------------- Install and config backend. -------------
# -------------------------------------------------------
backend_install()
{
    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        # Install, config and initialize OpenLDAP.
        openldap_install && \
        openldap_config && \
        openldap_data_initialize
        pla_install
    else
        # Install, config and initialize MySQL.
        mysql_install && \
        mysql_initialize && \
        postfixadmin_install
    fi
}
# -------------------------------------------------------
# ------------------- Cyrus-SASL ------------------------
# -------------------------------------------------------
cyrus_sasl_install()
{
    # Installation.
    install_pkg cyrus-sasl cyrus-sasl-lib cyrus-sasl-plain cyrus-sasl-ldap cyrus-sasl-md5

    # Enable services.
    chkconfig --level 35 saslauthd on
}

cyrus_sasl_config_ldap()
{
    ECHO_INFO "Config saslauthd: ${SASLAUTHD_CONF}"
    cat > ${SASLAUTHD_CONF} <<EOF
${CONF_MSG}
SOCKETDIR=${SASLAUTHD_SOCKETDIR}
MECH=ldap
FLAGS="-O /etc/saslauthd.conf"
EOF

    ECHO_INFO "${ETC_SASLAUTHD_CONF}"
    cat > ${ETC_SASLAUTHD_CONF} <<EOF
${CONF_MSG}
ldap_servers:      ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}
ldap_search_base:  ${LDAP_BASEDN}
ldap_timeout:      10
ldap_bind_dn:      ${LDAP_BINDDN}
ldap_bind_pw:      ${LDAP_BINDPW}
ldap_filter:       mail=%u@%r
EOF
}

cyrus_sasl_config_mysql()
{
    ECHO_INFO "Config saslauthd: ${SASLAUTHD_CONF}"
    cat > ${SASLAUTHD_CONF} <<EOF
${CONF_MSG}
SOCKETDIR=${SASLAUTHD_SOCKETDIR}
MECH=rimap
FLAGS="-r -O localhost"
EOF
}

# -------------------------------------------------------
# ------------------ Config Cyrus-SASL ------------------
# -------------------------------------------------------
cyrus_sasl_config()
{
    backup_file ${SASLAUTHD_CONF} ${ETC_SASLAUTHD_CONF}
    mkdir -p ${SASLAUTHD_SOCKETDIR}

    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        cyrus_sasl_config_ldap
    else
        cyrus_sasl_config_mysql
    fi
}

# -------------------------------------------------------
# ---------------------- Postfix ------------------------
# -------------------------------------------------------
postfix_install()
{
    # Installation.
    install_pkg postfix

    # Enable services.
    chkconfig --level 35 postfix on
}

postfix_config_basic()
{
    ECHO_INFO "Generate configuration file: ${SMTPD_CONF}"
    backup_file ${SMTPD_CONF}

    cat > ${SMTPD_CONF} <<EOF
${CONF_MSG}
pwcheck_method: saslauthd
mech_list: PLAIN LOGIN
EOF

    ECHO_INFO "Enable chroot for Postfix."
    backup_file ${POSTFIX_FILE_MASTER_CF}
    perl -pi -e 's/^(smtp.*inet)(.*)(n)(.*)(n)(.*smtpd)$/${1}${2}${3}${4}-${6}/' ${POSTFIX_FILE_MASTER_CF}

    ECHO_INFO "Copy /etc/hosts file to chrooted postfix."
    mkdir -p "${POSTFIX_CHROOT_DIR}/etc/"
    cp -f /etc/hosts ${POSTFIX_CHROOT_DIR}/etc/

    postconf -e myhostname=$(hostname)
    postconf -e mydomain=$(hostname)
    postconf -e myorigin=$(hostname)
    postconf -e inet_interfaces="all"
    postconf -e mynetworks="127.0.0.0/8"

    # We use 'maildir' format, not 'mbox'.
    postconf -e home_mailbox="Maildir/"

    echo "root: ${MAIL_ALIAS_ROOT}" >> /etc/postfix/aliases
    postconf -e alias_maps="hash:/etc/postfix/aliases"
    touch /etc/postfix/aliases
    postalias hash:/etc/postfix/aliases
    newaliases

    # Set message_size_limit.
    postconf -e message_size_limit="${MESSAGE_SIZE_LIMIT}"
    postconf -e virtual_mailbox_limit_override="yes"
    # Set maildir overquota. 
    postconf -e virtual_overquota_bounce="yes"
    postconf -e virtual_maildir_limit_message="${MAILDIR_LIMIT_MESSAGE}"

    #postconf -e smtpd_sender_restrictions="reject_unknown_sender_domain, reject_unlisted_sender, reject_unverified_sender, reject_sender_login_mismatch, reject_authenticated_sender_login_mismatch, reject_unauthenticated_sender_login_mismatch"

    ECHO_INFO "Setting up virtual domain configuration for Postfix."

    postconf -e virtual_minimum_uid="${VMAIL_USER_UID}"
    postconf -e virtual_uid_maps="static:${VMAIL_USER_UID}"
    postconf -e virtual_gid_maps="static:${VMAIL_USER_GID}"
    postconf -e virtual_mailbox_base="${VMAIL_USER_HOME_DIR}"
}

postfix_config_ldap()
{
    ECHO_INFO "Setting up 'mydestination'."

    ldap_virtual_domains_cf="${POSTFIX_ROOTDIR}/ldap_virtual_domains.cf"
    ldap_transport_maps_cf="${POSTFIX_ROOTDIR}/ldap_transport_maps.cf"
    ldap_accounts_cf="${POSTFIX_ROOTDIR}/ldap_accounts.cf"
    ldap_accountsmap_cf="${POSTFIX_ROOTDIR}/ldap_accountsmap.cf"
    ldap_alias_maps_cf="${POSTFIX_ROOTDIR}/ldap_alias_maps.cf"

    postconf -e mydestination="\$myhostname, localhost, localhost.\$myhostname, ldap:${ldap_virtual_domains_cf}"
    postconf -e relay_domains="\$mydestination"
    postconf -e transport_maps="ldap:${ldap_transport_maps_cf}"
    postconf -e virtual_mailbox_maps="ldap:${ldap_accounts_cf}, ldap:${ldap_accountsmap_cf}"
    postconf -e virtual_alias_maps="ldap:${ldap_alias_maps_cf}"
    postconf -e local_recipient_maps='$alias_maps $virtual_mailbox_maps'

    #
    # For mydestination = ldap:virtualdomains
    #
    ECHO_INFO "Setting up LDAP virtual domains: ${ldap_virtual_domains_cf}."

    cat > ${ldap_virtual_domains_cf} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
bind            = ${LDAP_BIND}
start_tls       = no
version         = ${LDAP_BIND_VERSION}
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = ${LDAP_BASEDN}
scope           = one
query_filter    = (o=%s)
result_attribute= o
debug_level     = 0
EOF

    #
    # LDAP transport maps
    #
    ECHO_INFO "Setting up LDAP transport_maps: ${ldap_transport_maps_cf}."

    cat > ${ldap_transport_maps_cf} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = ${LDAP_BASEDN}
scope           = one
query_filter    = (o=%s)
result_attribute= destinationIndicator
debug_level     = 0
EOF

    #
    # LDAP Virtual Users.
    #
    ECHO_INFO "Setting up LDAP virtual users: ${ldap_accounts_cf}, ${ldap_accountsmap_cf}."

    cat > ${ldap_accounts_cf} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = sub
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mailMessageStore
debug_level     = 0
EOF

    cat > ${ldap_accountsmap_cf} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = sub
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mail
debug_level     = 0
EOF

    ECHO_INFO "Setting up LDAP virtual aliases: ${ldap_alias_maps_cf}."

    cat > ${ldap_alias_maps_cf} <<EOF
${CONF_MSG}
server_host     = ${LDAP_SERVER_HOST}
server_port     = ${LDAP_SERVER_PORT}
version         = ${LDAP_BIND_VERSION}
bind            = ${LDAP_BIND}
start_tls       = no
bind_dn         = ${LDAP_BINDDN}
bind_pw         = ${LDAP_BINDPW}
search_base     = o=%d,${LDAP_BASEDN}
scope           = sub
query_filter    = (&(&(mail=%s)(objectClass=qmailUser))(accountStatus=active))
result_attribute= mailForwardingAddress
debug_level     = 0
EOF

    ECHO_INFO "Set file permission: Owner/Group -> postfix/postfix, Mode -> 0640."
    chown root:root ${ldap_virtual_domains_cf} \
        ${ldap_transport_maps_cf} \
        ${ldap_accounts_cf} \
        ${ldap_accountsmap_cf} \
        ${ldap_alias_maps_cf}

    chmod 0644 ${ldap_virtual_domains_cf} \
        ${ldap_transport_maps_cf} \
        ${ldap_accounts_cf} \
        ${ldap_accountsmap_cf} \
        ${ldap_alias_maps_cf}
}

postfix_config_mysql()
{
    ECHO_INFO "Setting up 'mydestination'."

    mysql_virtual_domains_cf="${POSTFIX_ROOTDIR}/mysql_virtual_domains.cf"
    mysql_transport_maps_cf="${POSTFIX_ROOTDIR}/mysql_transport_maps.cf"
    mysql_virtual_mailbox_maps_cf="${POSTFIX_ROOTDIR}/mysql_virtual_mailbox_maps.cf"
    mysql_virtual_mailbox_limit_maps_cf="${POSTFIX_ROOTDIR}/mysql_virtual_mailbox_limit_maps.cf"
    mysql_virtual_alias_maps_cf="${POSTFIX_ROOTDIR}/mysql_virtual_alias_maps.cf"

    postconf -e mydestination="\$myhostname, localhost, localhost.\$myhostname, mysql:${mysql_virtual_domains_cf}"
    postconf -e relay_domains="\$mydestination"
    postconf -e transport_maps="mysql:${mysql_transport_maps_cf}"
    postconf -e virtual_mailbox_maps="mysql:${mysql_virtual_mailbox_maps_cf}"
    postconf -e virtual_mailbox_limit_maps="mysql:${mysql_virtual_mailbox_limit_maps_cf}"
    postconf -e virtual_alias_maps="mysql:${mysql_virtual_alias_maps_cf}"
    postconf -e local_recipient_maps='$alias_maps $virtual_mailbox_maps'

    cat > ${mysql_transport_maps_cf} <<EOF
user        = ${MYSQL_BIND_USER}
password    = ${MYSQL_BIND_PW}
hosts       = ${MYSQL_SERVER}
port        = ${MYSQL_PORT}
dbname      = ${VMAIL_DB}
table       = domain
select_field= transport
where_field = domain
EOF

    cat > ${mysql_virtual_domains_cf} <<EOF
user        = ${MYSQL_BIND_USER}
password    = ${MYSQL_BIND_PW}
hosts       = ${MYSQL_SERVER}
port        = ${MYSQL_PORT}
dbname      = ${VMAIL_DB}
table       = domain
select_field= domain
where_field = domain
additional_conditions = AND active='1'
EOF

    cat > ${mysql_virtual_mailbox_maps_cf} <<EOF
user        = ${MYSQL_BIND_USER}
password    = ${MYSQL_BIND_PW}
hosts       = ${MYSQL_SERVER}
port        = ${MYSQL_PORT}
dbname      = ${VMAIL_DB}
table       = mailbox
select_field= maildir
where_field = username
additional_conditions = AND active='1'
EOF

    cat > ${mysql_virtual_mailbox_limit_maps_cf} <<EOF
user        = ${MYSQL_BIND_USER}
password    = ${MYSQL_BIND_PW}
hosts       = ${MYSQL_SERVER}
port        = ${MYSQL_PORT}
dbname      = ${VMAIL_DB}
table       = mailbox
select_field= quota
where_field = username
additional_conditions = AND active='1'
EOF

    cat > ${mysql_virtual_alias_maps_cf} <<EOF
user        = ${MYSQL_BIND_USER}
password    = ${MYSQL_BIND_PW}
hosts       = ${MYSQL_SERVER}
port        = ${MYSQL_PORT}
dbname      = ${VMAIL_DB}
table       = alias
select_field= goto
where_field = address
additional_conditions = AND active='1'
EOF

    ECHO_INFO "Set file permission: Owner/Group -> postfix/postfix, Mode -> 0640."
    chown root:root ${mysql_virtual_domains_cf} \
        ${mysql_transport_maps_cf} \
        ${mysql_virtual_mailbox_maps_cf} \
        ${mysql_virtual_mailbox_limit_maps_cf} \
        ${mysql_virtual_alias_maps_cf}

    chmod 0644 ${mysql_virtual_domains_cf} \
        ${mysql_transport_maps_cf} \
        ${mysql_virtual_mailbox_maps_cf} \
        ${mysql_virtual_mailbox_limit_maps_cf} \
        ${mysql_virtual_alias_maps_cf}
}

# Starting config.
postfix_config_virtual_host()
{
    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        postfix_config_ldap
    elif [ X"${BACKEND}" == X"MySQL" ]; then
        postfix_config_mysql
    else
        :
    fi
}

# ---------------------------------------------
# Postgrey.
# ---------------------------------------------
postgrey_install()
{
    # Installation.
    install_pkg postgrey

    # Enable services.
    chkconfig --level 35 postgrey on

    # Modify initialize script.
    perl -pi -e 's#^(OPTIONS=".*)(")#${1} --greylist-text="Spammer"${2}#' /etc/init.d/postgrey
}

postfix_config_sasl()
{
    ECHO_INFO "Setting up SASL configration for Postfix."

    #
    # For SASL auth
    #

    postconf -e smtpd_sasl_auth_enable="yes"
    postconf -e smtpd_sasl_local_domain=''
    postconf -e smtpd_sasl_security_options="noanonymous"
    postconf -e broken_sasl_auth_clients="yes"

    # For grey list.

    # Postgrey.
    postconf -e smtpd_recipient_restrictions="permit_mynetworks, reject_unauth_destination, check_policy_service unix:postgrey/socket, permit"

    # For non-grey list.

    #postconf -e smtpd_recipient_restrictions="permit_mynetworks, permit_sasl_authenticated, reject_unauth_destination"

    # Other 'smtpd_recipient_restrictions' options.

    #   reject_non_fqdn_hostname,
    #   reject_non_fqdn_sender,
    #   reject_non_fqdn_recipient,
    #   reject_unauth_pipelining,
    #   reject_invalid_hostname,
}

# ----------------------------------------------
# Maildrop.
# ----------------------------------------------
maildrop_install()
{
    # Installation.
    install_pkg courier-authlib maildrop maildrop-man
}

maildrop_config()
{
    ECHO_INFO "Generate configuration file: ${MAILDROPRC}."
    cat > ${MAILDROPRC} <<EOF
${CONF_MSG}
#
# logfile should be owned by user/group: ${VMAIL_USER_NAME}:${VMAIL_GROUP_NAME}, mode: 0640.
# A newsyslog configuration was created for logrotate.
#

logfile "${MAILDROP_LOGFILE}"

SHELL       = "/bin/sh"
HOME        = "${VMAIL_USER_HOME_DIR}"
MAILDIR     = "${MAILDIR_NAME}"

TO          = tolower("\$LOGNAME")  # 'username@domain.com'
EXTENSION   = "\$1"                 # default is 'spam'
RECIPIENT   = tolower("\$2")
USER        = "\$3"                 # 'username'
HOST        = "\$4"                 # 'domain.com'
SENDER      = "\$5"

USERHOME    = "\$HOME/\$HOST/\$USER"
MAILBOX     = "\$HOME/\$HOST/\$USER/\$MAILDIR"

#
# Only allow users listed in file '/etc/postfix/www_at_openbsdonly.org' send
# mail to user 'www@openbsdonly.org'.
# File '/etc/postfix/www_at_openbsdonly': one email address per line.
#
#if ( /^To:.*www@openbsdonly.org.*/ )
#{
#    if ( /^From:\s*(.*)/ && lookup( $MATCH1, '/etc/postfix/www_at_openbsdonly.org'))
#    {
#        MAILBOX="${MAILBOX}"
#    }
#    else
#    {
#        to /dev/null
#    }
#}

if ( \$EXTENSION = 'spam' )
{
    EXTENSION = 'Spam'
}

#
# \$HOME/.mailfilter
#   Owner UID/GID:  ${VMAIL_USER_UID}:${VMAIL_USER_GID}
#   Mode:   0600
#
\`test -r \$HOME/.mailfilter\`
if ( \$RETURNCODE == 0 )
{
    include \$HOME/.mailfilter
}

\`test -e \$MAILBOX\`
if ( \$RETURNCODE != 0 )
{
    # Create user home directory.
    \`mkdir -p \$USERHOME\`

    # Create Maildir.
    \`maildirmake \$MAILBOX && maildirmake -f \$EXTENSION \$MAILBOX \`

    # Auto-subscribe the subdirectory to imap server.
    \`print "INBOX.Sent\nINBOX.Trash\nINBOX.Drafts\nINBOX.Spam" > \$MAILBOX/courierimapsubscribed\`

    # Set permission.
    \`chown ${VMAIL_USER_UID}:${VMAIL_USER_GID} -R \$MAILBOX \`
    \`chmod 0700 \$USERHOME\`
}

if (/^X-Spam-Flag:.*YES/)
{
    log "Spam detected. Move to the SPAM Folder: \$MAILBOX/.\$EXTENSION"
    MAILBOX="\$MAILBOX/.\$EXTENSION/"
}

to \$MAILBOX
EOF

#    ECHO_INFO "Generate quota warnning message: /etc/quotawarnmsg."
#    sed -e "s/Mailer-Daemon@example.com/root@$(hostname)/" \
#        -e "s/support@example.com/root@$(hostname)/" /usr/local/share/doc/maildrop/quotawarnmsg > /etc/quotawarnmsg

    ECHO_INFO "Generate log file for maildrop: ${MAILDROP_LOGFILE}."
    touch ${MAILDROP_LOGFILE}
    chown ${VMAIL_USER_UID}:${VMAIL_USER_GID} ${MAILDROP_LOGFILE}
    chmod 0600 ${MAILDROP_LOGFILE}

    ECHO_INFO "Setting logrotate for maildrop: /etc/logrotate.d/maildrop."
    cat > /etc/logrotate.d/maildrop <<EOF
${CONF_MSG}
${MAILDROP_LOGFILE} {
    compress
    weekly
    rotate 5
    create 0600 ${VMAIL_USER_NAME} ${VMAIL_GROUP_NAME}
    missingok
    postrotate
        /sbin/killall -HUP syslogd
    endscript
}
EOF

    ECHO_INFO "Enable maildrop in postfix: ${POSTFIX_FILE_MAIN_CF}."
    postconf -e mailbox_command='maildrop'
    postconf -e virtual_transport='maildrop'
    postconf -e maildrop_destination_concurrency_limit='2'
    postconf -e maildrop_destination_recipient_limit='1'

    perl -pi -e 's#(.*user=vmail)(.*)(argv=)(.*)#${1}:vmail${2}${3}/usr/bin/maildrop -w 90 -d \${user}\@\${nexthop} \${extension} \${recipient} \${user} \${nexthop} \${sender}#' ${POSTFIX_FILE_MASTER_CF}
}

# --------------------------------------------
# Courier authlib: ldap & mysql
# --------------------------------------------
courier_authlib_ldap()
{
    # Installation.
    install_pkg courier-authlib-ldap

    # Configuration.
    ECHO_INFO "Setting up courier-authlib-ldap: ${AUTHDAEMONRC}."
    backup_file ${AUTHDAEMONRC}

    perl -pi -e 's/(authmodulelist=")(.*)(authldap)(.*)(")/${1}${3}${5}/' ${AUTHDAEMONRC}
    perl -pi -e 's/(authmodulelistorig=")(.*)(authldap)(.*)(")/${1}${3}${5}/' ${AUTHDAEMONRC}

    ECHO_INFO "Setting up courier-authlib-ldap: ${AUTHLDAPRC}."
    backup_file ${AUTHLDAPRC}

    cat > ${AUTHLDAPRC} <<EOF
${CONF_MSG}
LDAP_URI                ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}
LDAP_PROTOCOL_VERSION   3
LDAP_BASEDN             ${LDAP_BASEDN}
LDAP_BINDDN             ${LDAP_BINDDN}
LDAP_BINDPW             ${LDAP_BINDPW}
LDAP_TIMEOUT            5
LDAP_AUTHBIND           1
LDAP_FILTER             (&(objectClass=qmailUser)(accountStatus=active))
LDAP_GLOB_UID           ${VMAIL_USER_UID}
LDAP_GLOB_GID           ${VMAIL_USER_GID}
LDAP_HOMEDIR            homeDirectory
LDAP_MAILDIR            mailMessageStore
LDAP_MAILDIRQUOTA       mailQuota
LDAP_DEFAULTDELIVERY    defaultDelivery
LDAP_FULLNAME           cn
LDAP_CLEARPW            clearPassword
LDAP_CRYPTPW            userPassword
LDAP_DEREF              never
LDAP_TLS                0
EOF
}

courier_authlib_mysql()
{
    # Installation.
    install_pkg courier-authlib-mysql

    # Configuration.
    ECHO_INFO "Setting up courier-authlib-mysql: ${AUTHDAEMONRC}."
    backup_file ${AUTHDAEMONRC}

    perl -pi -e 's/(authmodulelist=")(.*)(authmysql)(.*)(")/${1}${3}${5}/' ${AUTHDAEMONRC}
    perl -pi -e 's/(authmodulelistorig=")(.*)(authmysql)(.*)(")/${1}${3}${5}/' ${AUTHDAEMONRC}

    ECHO_INFO "Setting up courier-authlib-mysql: ${AUTHMYSQLRC}."
    backup_file ${AUTHMYSQLRC}

    cat > ${AUTHMYSQLRC} <<EOF
MYSQL_SERVER        ${MYSQL_SERVER}
MYSQL_PORT          ${MYSQL_PORT}
MYSQL_USERNAME      ${MYSQL_BIND_USER}
MYSQL_PASSWORD      ${MYSQL_BIND_PW}
MYSQL_SOCKET        ${MYSQL_SOCKET}

MYSQL_UID_FIELD     ${VMAIL_USER_UID}
MYSQL_GID_FIELD     ${VMAIL_USER_GID}

MYSQL_DATABASE      ${VMAIL_DB}
MYSQL_USER_TABLE    mailbox

MYSQL_HOME_FIELD    '${VMAIL_USER_HOME_DIR}/'
MYSQL_LOGIN_FIELD   username
MYSQL_CRYPT_PWFIELD password

MYSQL_MAILDIR_FIELD CONCAT('${VMAIL_USER_HOME_DIR}/',maildir)
MYSQL_QUOTA_FIELD   CONCAT(quota,'S')
MYSQL_NAME_FIELD    name
MYSQL_WHERE_CLAUSE  active='1'
EOF
}

courier_authlib()
{
    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        courier_authlib_ldap
    else
        courier_authlib_mysql
    fi

    ECHO_INFO "Setting directory permission: /var/spool/authdaemon/ -> 0755"
    mkdir -p /var/spool/authdaemon
    chown daemon:daemon /var/spool/authdaemon
    chmod 0755 /var/spool/authdaemon/
}

# --------------------------------------------
# Courier POP3/IMAP.
# --------------------------------------------
courier_imap()
{
    # Installation.
    install_pkg courier-imap

    chkconfig --level 35 courier-imap on
}

create_user_maildir()
{
    for user in ${FIRST_USER} ${FIRST_DOMAIN_ADMIN_NAME}; do
        user_home="${VMAIL_USER_HOME_DIR}/${FIRST_DOMAIN}/${user}"
        user_maildir="${user_home}/${MAILDIR_NAME}"

        ECHO_INFO "Create and set maildir folder for user: ${user}."

        mkdir -p ${user_home}
        maildirmake ${user_maildir} && maildirmake -f Spam ${user_maildir}

        echo -e "INBOX.Sent\nINBOX.Trash\nINBOX.Drafts\nINBOX.Spam" > ${user_maildir}/courierimapsubscribed

        chown -R ${VMAIL_USER_UID}:${VMAIL_USER_GID} ${VMAIL_USER_HOME_DIR}/${FIRST_DOMAIN}/
        chmod -R 0700 ${VMAIL_USER_HOME_DIR}/${FIRST_DOMAIN}/
    done
}

# --------------------------------------------
# ClamAV.
# --------------------------------------------
clamav_install()
{
    # Installation.
    install_pkg clamd clamav clamav-db

    # Enable services.
    chkconfig --level 35 clamd on
}

clamav_config()
{
    ECHO_INFO "Disable TCPAddr in clamd."
    perl -pi -e 's/^(TCPAddr )/${1}no #/' /etc/clamd.conf

    ECHO_INFO "Set freshclam PidFile: /var/run/clamav/freshclam.pid."
    perl -pi -e 's-^#(PidFile)(.*)-${1} /var/run/clamav/freshclam.pid #${2}-' /etc/freshclam.conf

    ECHO_INFO "Copy freshclam initialize startup script, and enable it."
    cp ${SAMPLE_DIR}/freshclam /etc/rc.d/init.d/
    chmod +x /etc/rc.d/init.d/freshclam
    chkconfig --level 35 freshclam on
}

# --------------------------------------------
# Amavisd-new.
# --------------------------------------------
amavisd_install()
{
    # Installation.
    # It will install unrar, unarj and SpamAssassin as dependence.
    install_pkg amavisd-new

    # Force installation.
    rpm -ivh --force ${PKG_DIR}/perl-File-Temp-*

    # Enable services.
    chkconfig --level 35 amavisd on
    chkconfig --level 35 spamassassin on
}

amavisd_config()
{
    ECHO_INFO "Backup amavisd configuration file: ${AMAVISD_CONF}."
    backup_file ${AMAVISD_CONF}

    # Configure /etc/amavisd.conf.
    ECHO_INFO "Configure amavisd-new: ${AMAVISD_CONF}."
    perl -pi -e 's/^(\$max_servers)/$1\ =\ 15\;\t#/' ${AMAVISD_CONF}

    # Use amavisd daemon user.
    #perl -pi -e 's/^(\$daemon_user)/$1\ =\ "clamav"\;\t#/' ${AMAVISD_CONF}
    #perl -pi -e 's/^(\$daemon_group)/$1\ =\ "clamav"\;\t#/' ${AMAVISD_CONF}

    export HOSTNAME="$(hostname)"
    perl -pi -e 's/^(\$mydomain)/$1\ =\ \"$ENV{'HOSTNAME'}\"\;\t#/' ${AMAVISD_CONF}

    # Set default score.
    #perl -pi -e 's/(.*)(sa_tag_level_deflt)(.*)/${1}${2} = 4.0; #${3}/' ${AMAVISD_CONF}
    #perl -pi -e 's/(.*)(sa_tag2_level_deflt)(.*)/${1}${2} = 6; #${3}/' ${AMAVISD_CONF}
    #perl -pi -e 's/(.*)(sa_kill_level_deflt)(.*)/${1}${2} = 10; #${3}/' ${AMAVISD_CONF}

    # Set admin address.
    perl -pi -e 's#(virus_admin.*= ")(virusalert)(.*)#${1}root${3}#' ${AMAVISD_CONF}
    perl -pi -e 's#(mailfrom_notify_admin.*= ")(virusalert)(.*)#${1}root${3}#' ${AMAVISD_CONF}
    perl -pi -e 's#(mailfrom_notify_recip.*= ")(virusalert)(.*)#${1}root${3}#' ${AMAVISD_CONF}
    perl -pi -e 's#(mailfrom_notify_spamadmin.*= ")(spam.police)(.*)#${1}root${3}#' ${AMAVISD_CONF}

    # Remove the content from '@av_scanners' to the end of file.
    new_conf="$(sed '/\@av_scanners/,$d' ${AMAVISD_CONF})"

    # Generate new configration file(Part).
    echo -e "${new_conf}" > ${AMAVISD_CONF}

    # Set pid_file.
    #echo '$pid_file = "/var/run/clamav/amavisd.pid";' >> ${AMAVISD_CONF}

    # Set listen IP/PORT.
    cat >> ${AMAVISD_CONF} <<EOF
\$notify_method  = 'smtp:[127.0.0.1]:10025';
\$forward_method = 'smtp:[127.0.0.1]:10025';

EOF

    # Set default action.
    cat >> ${AMAVISD_CONF} <<EOF
\$final_virus_destiny      = D_DISCARD;
\$final_banned_destiny     = D_PASS;
\$final_spam_destiny       = D_PASS;
\$final_bad_header_destiny = D_PASS;

EOF

    cat >> ${AMAVISD_CONF} <<EOF
@av_scanners = (

    #### http://www.clamav.net/
    ['ClamAV-clamd',
    \&ask_daemon, ["CONTSCAN {}\n", "/tmp/clamd.socket"],
    qr/\bOK$/, qr/\bFOUND$/,
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
);

@av_scanners_backup = (

    ### http://www.clamav.net/   - backs up clamd or Mail::ClamAV
    ['ClamAV-clamscan', 'clamscan',
    "--stdout --disable-summary -r --tempdir=$TEMPBASE {}", [0], [1],
    qr/^.*?: (?!Infected Archive)(.*) FOUND$/ ],
);

# SpamAssassin debugging. Default if off(0).
\$sa_debug = 0;
\$sa_spam_modifies_subj = 1;

1;  # insure a defined return
EOF
    # ------------- END configure /etc/amavisd.conf ------------

    # Configure postfix: master.cf.
    cat >> ${POSTFIX_FILE_MASTER_CF} <<EOF
smtp-amavis unix -  -   -   -   2  smtp
    -o smtp_data_done_timeout=1200
    -o smtp_send_xforward_command=yes
    -o disable_dns_lookups=yes
    -o max_use=20

127.0.0.1:10025 inet n  -   -   -   -  smtpd
    -o content_filter=
    -o local_recipient_maps=
    -o relay_recipient_maps=
    -o smtpd_restriction_classes=
    -o smtpd_delay_reject=no
    -o smtpd_client_restrictions=permit_mynetworks,reject
    -o smtpd_helo_restrictions=
    -o smtpd_sender_restrictions=
    -o smtpd_recipient_restrictions=permit_mynetworks,reject
    -o mynetworks_style=host
    -o mynetworks=127.0.0.0/8
    -o strict_rfc821_envelopes=yes
    -o smtpd_error_sleep_time=0
    -o smtpd_soft_error_limit=1001
    -o smtpd_hard_error_limit=1000
    -o smtpd_client_connection_count_limit=0
    -o smtpd_client_connection_rate_limit=0
    -o receive_override_options=no_header_body_checks,no_unknown_recipient_checks
EOF

    postconf -e 'content_filter=smtp-amavis:[127.0.0.1]:10024'
}

# SpamAssassin
sa_config()
{
    backup_file ${SA_LOCAL_CF}

    ECHO_INFO "Generate new configuration file: ${SA_LOCAL_CF}."
    cp -f ${SAMPLE_DIR}/sa.local.cf ${SA_LOCAL_CF}
}

# ---------------------------------------------------------
# SqruirrelMail.
# ---------------------------------------------------------
enable_sm_plugins()
{
    # We do *NOT* use 'conf.pl' to enable plugins, because it's not easy to
    # control in non-interactive mode, so we use 'perl' to modify the config
    # file directly.

    ECHO_INFO "Enable SquirrelMail plugins: ${ENABLED_PLUGINS}"
    
    # Disable all exist plugins first.
    perl -pi -e 's/^(\$plugins*)/\/\/$1/' ${SM_CONFIG}

    if [ X"$#" != X"0" ]; then
        counter=0

        while [ ${counter} -lt $# ]; do
            plugin_name="\$$((counter+1))"
            echo "\$plugins[${counter}]='$(eval echo ${plugin_name})';" >> ${SM_CONFIG}
            counter=$((counter+1))
        done
    else
        echo "Usage: enable_plugins plugin1 [plugin2 plugin3 ...]"
    fi
}

sm_install()
{
    cd ${MISC_DIR}

    # Extract source tarball.
    extract_pkg ${SM_TARBALL}

    ECHO_INFO "Move squirrelmail to httpd SERVERROOT: ${SM_HTTPD_ROOT}."
    mv squirrelmail-${SM_VERSION} ${SM_HTTPD_ROOT}

    ECHO_INFO "Set correct permission for squirrelmail: ${SM_HTTPD_ROOT}."
    chown -R apache:apache ${SM_HTTPD_ROOT}
    chmod -R 755 ${SM_HTTPD_ROOT}
    chmod 0000 ${SM_HTTPD_ROOT}/{AUTHORS,ChangeLog,COPYING,INSTALL,README,ReleaseNotes,UPGRADE}

    ECHO_INFO "Create directory alias for squirrelmail in Apache: ${HTTPD_DOCUMENTROOT}/mail/."
    cat > ${HTTPD_CONF_DIR}/squirrelmail.conf <<EOF
${CONF_MSG}
Alias /mail "${HTTPD_SERVERROOT}/squirrelmail-${SM_VERSION}/"
Alias /webmail "${HTTPD_SERVERROOT}/squirrelmail-${SM_VERSION}/"
EOF

    ECHO_INFO "Create directories to storage squirrelmail data and attachments: ${SM_DATA}, ${SM_ATTACH}."

    mkdir -p ${SM_DATA} ${SM_ATTACH}
    chown apache:apache ${SM_DATA} ${SM_ATTACH}
    chmod 730 ${SM_ATTACH}

    ECHO_INFO "Access the webmail from URL: http://${hostname}/mail/"
}

sm_config()
{
    ECHO_INFO "Setting up configuration file for SquirrelMail."
    ${SM_CONF_PL} <<EOF
2
1
$(hostname)
A
4
127.0.0.1
B
4
127.0.0.1
R
4
1
${SM_DATA}
2
${SM_ATTACH}
R
6
1
+
${LDAP_SERVER_HOST}
${LDAP_BASEDN}
${LDAP_SERVER_PORT}
utf-8
Global LDAP Address Book

${LDAP_BINDDN}
${LDAP_BINDPW}
3
d
R
10
1
${SM_DEFAULT_LOCALE}
2
${SM_DEFAULT_CHARSET}
R
D
courier

S

Q
EOF
}

#
# For squirrelmail plugin: change_ldappass.
#

sm_plugin_change_ldappass()
{
    cd ${MISC_DIR}
    extract_pkg ${PLUGIN_CHANGE_LDAPPASS_TARBALL}

    ECHO_INFO "Move plugin to: ${SM_PLUGIN_DIR}."
    mv change_ldappass ${SM_PLUGIN_DIR}
    chown -R apache:apache ${SM_PLUGIN_DIR}
    chmod -R 0755 ${SM_PLUGIN_DIR}

    cd ${SM_PLUGIN_DIR}/change_ldappass/

    ECHO_INFO "Generate configration file: ${SM_PLUGIN_DIR}/change_ldappass/config.php."
    cat >${PLUGIN_CHANGE_LDAPPASS_CONFIG} <<EOF
<?php
${CONF_MSG}
\$ldap_server = 'ldap://${LDAP_SERVER_HOST}:${LDAP_SERVER_PORT}';
\$ldap_protocol_version = ${LDAP_BIND_VERSION};
\$ldap_password_field = 'userPassword';
\$ldap_user_field = 'mail';
\$ldap_base_dn = '${LDAP_BASEDN}';
\$ldap_filter = '(&(objectClass=qmailUser)(accountStatus=active))';
\$query_dn="${LDAP_BINDDN}";
\$query_pw="${LDAP_BINDPW}";
\$ldap_bind_as_manager = false;
\$ldap_bind_as_manager = false;
\$ldap_manager_dn='';
\$ldap_manager_pw='';
\$change_smb=false;
\$debug=false;
EOF

    chown apache:apache ${PLUGIN_CHANGE_LDAPPASS_CONFIG}
    chmod 644 ${PLUGIN_CHANGE_LDAPPASS_CONFIG}
}

#
# For squirrelmail plugin: change_ldappass.
#

sm_plugin_compatibility()
{
    cd ${MISC_DIR}
    extract_pkg ${PLUGIN_COMPATIBILITY_TARBALL}

    ECHO_INFO "Move plugin to: ${SM_PLUGIN_DIR}."
    mv compatibility ${SM_PLUGIN_DIR}
    chown -R apache:apache ${SM_PLUGIN_DIR}/compatibility/
    chmod -R 0755 ${SM_PLUGIN_DIR}/compatibility/
}

#
# For squirrelmail plugin: Check Quota.
#

sm_plugin_check_quota()
{
    # Installation.
    cd ${MISC_DIR}
    extract_pkg ${PLUGIN_CHECK_QUOTA_TARBALL}

    ECHO_INFO "Move plugin to: ${SM_PLUGIN_DIR}."
    mv check_quota ${SM_PLUGIN_DIR}
    chown -R apache:apache ${SM_PLUGIN_DIR}/check_quota/
    chmod -R 0755 ${SM_PLUGIN_DIR}/check_quota/

    # Configure.
    ECHO_INFO "Generate configuration file for plugin: check_quota."
    cp ${SM_PLUGIN_DIR}/check_quota/config.sample.php ${SM_PLUGIN_DIR}/check_quota/config.php
    chown -R apache:apache ${SM_PLUGIN_DIR}/check_quota/config.php
    chmod -R 0755 ${SM_PLUGIN_DIR}/check_quota/config.php

    ECHO_INFO "Configure plugin: check_quota."
    perl -pi -e 's/(.*)(quota_type)(.*)0;/${1}${2}${3}1;/' ${SM_PLUGIN_DIR}/check_quota/config.php
}

#
# For SquirrelMail plugin: select_language.
#

sm_plugin_select_language()
{
    ECHO_INFO "Prepare plugin: select language."

    cd ${MISC_DIR}
    extract_pkg ${PLUGIN_SELECT_LANGUAGE_TARBALL}

    mv select_language ${SM_PLUGIN_DIR}
    chown -R apache:apache ${SM_PLUGIN_DIR}/select_language
    chmod -R 755 ${SM_PLUGIN_DIR}/select_language
}

#
# For SquirrelMail translations.
#

sm_translations()
{
    cd ${MISC_DIR}

    extract_pkg ${SM_TRANSLATIONS_TARBALL} /tmp
    
    ECHO_INFO "Copy SquirrelMail translations to ${SM_HTTPD_ROOT}/"
    cp -rf /tmp/locale/* ${SM_HTTPD_ROOT}/locale/
    cp -rf /tmp/images/* ${SM_HTTPD_ROOT}/images/
    cp -rf /tmp/help/* ${SM_HTTPD_ROOT}/help/
}

convert_translation_locale()
{
    # convert_locale zh_CN zh_CN.GB2312 zh_CN.UTF8 gb2312 utf-8
    #                $1    $2           $3         $4     $5
    export language="$1"
    export locale_old="$2"
    export locale_new="$3"
    export charset_old="$4"
    export charset_new="$5"

    ECHO_INFO "Convert translation locale: $language"
    ECHO_INFO "LOCALE: $2 -> $3. CHARSET: $4 -> $5."

    if [ -d ${SM_HTTPD_ROOT}/locale/${language}/ ]; then
        cd ${SM_HTTPD_ROOT}/locale/${language}/LC_MESSAGES/
        cp squirrelmail.po squirrelmail.po.${charset_old}
        iconv -f ${charset_old} -t ${charset_new} squirrelmail.po.${charset_old} > squirrelmail.po

        cd ${SM_HTTPD_ROOT}/locale/${language}/
        cp setup.php setup.php.bak
        perl -pi -e 's/(.*)$ENV{"charset_old"}(.*)/$1$ENV{"charset_new"}$2/' setup.php
        perl -pi -e 's/(.*)$ENV{"locale_old"}(.*)/$1$ENV{"locale_new"}$2/' setup.php
    fi

    if [ -d ${SM_HTTPD_ROOT}/help/${language} ]; then

        cd ${SM_HTTPD_ROOT}/help/${language}

        for i in $(ls *); do
            cp $i $i.bak
            iconv -f ${charset_old} -t ${charset_new} $i.bak >$i
        done
    fi

    cd ${SM_HTTPD_ROOT}/functions/
    cp i18n.php i18n.php.bak
    perl -pi -e 's/(.*)$ENV{"charset_old"}(.*)/$1$ENV{"charset_new"}$2/' i18n.php
    perl -pi -e 's/(.*)$ENV{"locale_old"}(.*)/$1$ENV{"locale_new"}$2/' i18n.php
}

# -----------------------
# Roundcube.
# -----------------------
rcd_install()
{
    cd ${MISC_DIR}

    # Extract source tarball.
    extract_pkg ${RCD_TARBALL}

    ECHO_INFO "Move Roundcube to httpd SERVERROOT: ${RCD_HTTPD_ROOT}."
    mv roundcubemail-${RCD_VERSION} ${RCD_HTTPD_ROOT}

    ECHO_INFO "Set correct permission for Roundcubemail: ${RCD_HTTPD_ROOT}."
    chown -R root:root ${RCD_HTTPD_ROOT}
    chown -R apache:apache ${RCD_HTTPD_ROOT}/{temp,logs}
    chmod 0000 ${RCD_HTTPD_ROOT}/{CHANGELOG,INSTALL,LICENSE,README,UPGRADING,installer}
}

rcd_config()
{
    ECHO_INFO "Import MySQL database for Roundcubemail."

    mysql -uroot -p${MYSQL_ROOTPW} <<EOF
CREATE DATABASE ${RCD_DB} DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
GRANT ALL PRIVILEGES ON ${RCD_DB}.* TO ${RCD_DB_USER}@localhost IDENTIFIED BY '${RCD_DB_PASSWD}';

use ${RCD_DB};
source ${RCD_HTTPD_ROOT}/SQL/mysql5.initial.sql;

flush privileges;
EOF

    ECHO_INFO "Configure database for Roundcubemail: ${RCD_HTTPD_ROOT}/config/*."
    cd ${RCD_HTTPD_ROOT}/config/
    cp -f db.inc.php.dist db.inc.php
    cp -f main.inc.php.dist main.inc.php

    cd ${RCD_HTTPD_ROOT}/config/
    if [ X"${BACKEND}" == X"MySQL" ]; then
        export RCD_DB
        export RCD_DB_USER
        export RCD_DB_PASSWD
        perl -pi -e 's#(.*db_dsnw.*= )(.*)#${1}"mysql://$ENV{'RCD_DB_USER'}:$ENV{'RCD_DB_PASSWD'}\@localhost/$ENV{'RCD_DB'}";#' db.inc.php
    else
        :
    fi

    perl -pi -e 's#(.*default_host.*= )(.*)#${1}"127.0.0.1";#' main.inc.php
    perl -pi -e 's#(.*smtp_server.*= )(.*)#${1}"127.0.0.1";#' main.inc.php
    perl -pi -e 's#(.*smtp_user.*= )(.*)#${1}"%u";#' main.inc.php
    perl -pi -e 's#(.*smtp_pass.*= )(.*)#${1}"%p";#' main.inc.php
    perl -pi -e 's#Junk#Spam#' main.inc.php
    perl -pi -e 's#(.*create_default_folders.*)(FALSE)(.*)#${1}TRUE${3}#' main.inc.php
    perl -pi -e 's#(.*locale_string.*)(en)(.*)#${1}zh_CN${3}#' main.inc.php

    ECHO_INFO "Create directory alias for Roundcubemail."
    cat > ${HTTPD_CONF_DIR}/roundcubemail.conf <<EOF
${CONF_MSG}
Alias /mail "${HTTPD_SERVERROOT}/roundcubemail-${RCD_VERSION}/"
Alias /webmail "${HTTPD_SERVERROOT}/roundcubemail-${RCD_VERSION}/"
EOF
    ECHO_INFO "URL of Roundcube: http://$(hostname)/mail/"
    ECHO_INFO "URL of Roundcube: http://$(hostname)/webmail/"
}

# -----------------------------
# PostfixAdmin.
# -----------------------------
postfixadmin_install()
{
    cd ${MISC_DIR}

    ECHO_INFO "Extract PostfixAdmin: ${POSTFIXADMIN_TARBALL}..."
    extract_pkg ${POSTFIXADMIN_TARBALL} ${HTTPD_SERVERROOT}

    ECHO_INFO "Set file permission for PostfixAdmin."
    chown -R apache:apache ${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/
    chmod -R 755 ${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/
    mv ${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/setup.php ${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/setup.php.${DATE}

    ECHO_INFO "Create directory alias for PostfixAdmin in Apache."
    cat > ${HTTPD_CONF_DIR}/postfixadmin.conf <<EOF
${CONF_MSG}
Alias /postfixadmin "${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/"
EOF

    cat <<EOF
URL of PostfixAdmin:
    - Site Admin (aka superadmin) view, located at http://$(hostname)/postfixadmin/admin/.
    - Domain Admin view, located at http://$(hostname)/postfixadmin/.
    - User Admin View, located at http://$(hostname)/postfixadmin/users/
EOF

    cd ${HTTPD_SERVERROOT}/postfixadmin-${POSTFIXADMIN_VERSION}/
    perl -pi -e 's#(.*configured.*= )(.*)#${1}"true";#' config.inc.php
    perl -pi -e 's#(.*default_language.*= )(.*)#${1}"cn";#' config.inc.php

    export MYSQL_ADMIN_USER
    export MYSQL_ADMIN_PW
    export VMAIL_DB
    perl -pi -e 's#(.*database_user.*= )(.*)#${1}"$ENV{'MYSQL_ADMIN_USER'}";#' config.inc.php
    perl -pi -e 's#(.*database_password.*= )(.*)#${1}"$ENV{'MYSQL_ADMIN_PW'}";#' config.inc.php
    perl -pi -e 's#(.*database_name.*= )(.*)#${1}"$ENV{'VMAIL_DB'}";#' config.inc.php

    export MAIL_ALIAS_ROOT
    perl -pi -e 's#(.*admin_email.*= )(.*)#${1}"$ENV{'MAIL_ALIAS_ROOT'}";#' config.inc.php

    perl -pi -e 's#(.*domain_path.*= )(.*)#${1}"YES";#' config.inc.php
    perl -pi -e 's#(.*domain_in_mailbox.*= )(.*)#${1}"NO";#' config.inc.php
    perl -pi -e 's#(.*quota.*= )(.*)(NO)(.*)#${1}"YES";#' config.inc.php
    perl -pi -e 's#(.*transport.*= )(.*)(NO)(.*)#${1}"YES";#' config.inc.php
    perl -pi -e 's#(.*virtual.*,)#${1}"maildrop",#' config.inc.php
    perl -pi -e 's#(.*transport_default.*= )(.*)#${1}"maildrop";#' config.inc.php

    perl -pi -e 's#(.*backup.*= )(.*)(YES)(.*)#${1}"NO";#' config.inc.php
    perl -pi -e 's#(.*fetchmail.*= )(.*)(YES)(.*)#${1}"NO";#' config.inc.php
    perl -pi -e 's#(.*show_footer_text.*= )(.*)(YES)(.*)#${1}"NO";#' config.inc.php

    perl -pi -e 's#(.*maildir.*=.*fDomain.*/.*fUsername.*)(/)(.*)#${1}/Maildir/${3}#' create-mailbox.php
}

# -------------------------------------------------
# Web Mail.
# -------------------------------------------------
# *********
# For SquirrelMail Translations.
# *********
webmail()
{
    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
        # ------------------------------------------------
        # SquirrelMail and plugins.
        # ------------------------------------------------
        sm_install && \
        sm_config

        sm_translations && \
        convert_translation_locale 'zh_CN' 'zh_CN.GB2312' 'zh_CN.UTF8' 'gb2312' 'utf-8'
        convert_translation_locale 'zh_TW' 'zh_CN.BIG5' 'zh_CN.UTF8' 'big5' 'utf-8'

        # Plugins.
        sm_plugin_change_ldappass
        sm_plugin_compatibility
        sm_plugin_check_quota
        sm_plugin_select_language

        # Enable all defined plugins.
        enable_sm_plugins ${ENABLED_PLUGINS}
    else
        rcd_install && \
        rcd_config
    fi
}

# -------------------------------------------------
# Mailgraph
# -------------------------------------------------
mailgraph_install()
{
    ECHO_INFO "Add mailgraph for mail system, you can visit it via URL:"
    ECHO_INFO "http://$(hostname)/cgi-bin/mailgraph/mailgraph.cgi"

    install_pkg rrdtool perl-rrdtool perl-File-Tail

    mkdir -p ${HTTPD_SERVERROOT}/cgi-bin/mailgraph/
    cp ${SAMPLE_DIR}/mailgraph/mailgraph.cgi ${HTTPD_SERVERROOT}/cgi-bin/mailgraph/
    chmod 755 ${HTTPD_SERVERROOT}/cgi-bin/mailgraph/mailgraph.cgi

    cp ${SAMPLE_DIR}/mailgraph/mailgraph.css ${HTTPD_DOCUMENTROOT}/mailgraph.css

    cp ${SAMPLE_DIR}/mailgraph/mailgraph.pl /usr/local/bin/
    chmod 755 /usr/local/bin/mailgraph.pl

    cp ${SAMPLE_DIR}/mailgraph/mailgraph-init /etc/init.d/mailgraph
    chmod 755 /etc/init.d/mailgraph
    chkconfig --level 35 mailgraph on
}

# ************************************************************************
# *************************** Script Main ********************************
# ************************************************************************

# ------------------------------------------------
# User/Group: vmail
# ------------------------------------------------
adduser_vmail

# ------------------------------------------------
# Apache & PHP.
# ------------------------------------------------
apache_php_install && \
apache_php_config

# ------------------------------------------------
# Install & Config Backend: OpenLDAP or MySQL.
# ------------------------------------------------
backend_install

# ------------------------------------------------
# Cyrus-SASL.
# ------------------------------------------------
cyrus_sasl_install && \
cyrus_sasl_config

# ------------------------------------------------
# Postfix.
# ------------------------------------------------
postfix_install && \
postfix_config_basic && \
postfix_config_virtual_host && \
postgrey_install && \
postfix_config_sasl

# ------------------------------------------------
# Maildrop.
# ------------------------------------------------
maildrop_install && \
maildrop_config

# ------------------------------------------------
# Courier authlib-ldap.
# ------------------------------------------------
courier_authlib && \
courier_imap && \
create_user_maildir

# ------------------------------------------------
# Courier authlib-ldap.
# ------------------------------------------------
clamav_install && \
clamav_config

# ------------------------------------------------
# Amavisd-new. (plus unrar, unarj, SpamAssassin)
# ------------------------------------------------
amavisd_install && \
amavisd_config && \
sa_config

# ------------------------------------------------
# WebMail.
# ------------------------------------------------
webmail

# -----------------------------------------------
# Mailgraph
# -----------------------------------------------
mailgraph_install



cat <<EOF

# ***********************************************************************
# Congratulations, mail server installation complete.
# ***********************************************************************

EOF

# Some useful tools.
echo -n "Would you like to run freshclam now? [Y|n]"
read ANSWER
case $ANSWER in
    N|n ) ECHO_INFO "Skip freshclam." ;;
    Y|y|* ) freshclam ;;
esac

